#ifndef NETLIB_THREADLOCAL_H
#define NETLIB_THREADLOCAL_H

// 线程私有数据类（线程本地类），用于TSD(非POD-C语言内置类型）的存储
// 该类型创建一份，其他线程都会有一份，但它们的值各自独立为线程私有
// 线程内部维护一个指针链表，每一个TSD类型都会在链表上注册

#include "Mutex.h"
#include "noncopyable.h"

#include <pthread.h>

namespace netlib
{

template<typename T>
class ThreadLocal : noncopyable // 不可拷贝
{
public:
    ThreadLocal()
    { MCHECK(pthread_key_create(&pkey_, &ThreadLocal::destructor)); }

    // 析构函数并没有销毁数据，而是在构造函数中注册了ThreadLocal::destructor来销毁的
    ~ThreadLocal() { MCHECK(pthread_key_delete(pkey_)); }

    T& value() // 获取线程私有数据
    {
        T* perThreadValue = static_cast<T*>(pthread_getspecific(pkey_));
        if (!perThreadValue) // 如果指针为空，说明未创建，由我们手动创建
        {
            T* newObj = new T();
            MCHECK(pthread_setspecific(pkey_, newObj)); // 设置到线程内部
            perThreadValue = newObj;
        }
        return *perThreadValue;
    }

private:

    static void destructor(void *x) // 向系统注册的销毁函数，系统自动调用
    {
        T* obj = static_cast<T*>(x);

        //T_must_be_complete_type防止不完全类型导致程序崩溃
        typedef char T_must_be_complete_type[sizeof(T) == 0 ? -1 : 1];
        T_must_be_complete_type dummy; (void) dummy;
        delete obj;
    }

private:
  pthread_key_t pkey_;      // 线程私有数据标识

}; // class ThreadLocal end

} // namespace netlib end

#endif